/*
Brick And Blast, a crossplatform breakout game.
 Copyright (C) 2008-2010 Julien CLEMENT (andematunum@gmail.com)
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include "GameObject.h"
#include "Level.h"
#include "Collider.h"

#include <iostream>
using namespace std;

/**
* file   GameObject.cpp
* date   Sam 26 déc 2009 12:22:37 CET
* brief  TODO
*/

GameObject::
GameObject(GameObjectType type,
           GameObjectShape shape,
           SDL_Point& initPosition,
           SDL_TextureID initTexture)
: shape_(shape), type_(type), pixel_position_(initPosition),
  pixel_position_changed_(true), alive_(true), active_(true),
  fadeout_(255) {
  
  set_texture(initTexture, true);
}

void
GameObject::
compute_size () {
  switch(shape_) {
    case GAME_OBJECT_RECTANGLE: {
      SDL_QueryTexture(texture_,NULL,NULL,
        &size_.rect.w, &size_.rect.h);
    }
    break;
    case GAME_OBJECT_CIRCLE: {
      int w,h;
      SDL_QueryTexture(texture_,NULL,NULL,&w,&h);
      if (w != h) {
        cerr << "*** ERROR: Non square texture is not allowed for a circular object." << endl;
        cerr << "           Size: " << w << " x " << h << endl;
      }
      size_.r = static_cast<int>(round((double)w / 2.));
    }
    break;
    default: {
      cerr << "*** ERROR: Unknown shape code: " << shape_ << endl;
    }
    break;
  }

  update_pixel_rect();
}

void
GameObject::
update_pixel_rect () {
  rect_.x = rect_next_.x;
  rect_.y = rect_next_.y;
  rect_.w = rect_next_.w;
  rect_.h = rect_next_.h;
}

void
GameObject::
calculate_next_pixel_rect () {
  switch(shape_) {
    case GAME_OBJECT_RECTANGLE: {
      rect_next_.x = pixel_position_next_.x;
      rect_next_.y = pixel_position_next_.y;
      rect_next_.w = size_.rect.w;
      rect_next_.h = size_.rect.h;
    }
    break;
    case GAME_OBJECT_CIRCLE: {
      rect_next_.x = pixel_position_next_.x - size_.r;
      rect_next_.y = pixel_position_next_.y - size_.r;
      rect_next_.w = 2 * size_.r;
      rect_next_.h = rect_next_.w;
    }
    break;
    default: {
      cerr << "*** ERROR: Unknown shape code: " << shape_ << endl;
    }
    break;
  }
}

void
GameObject::
set_texture (SDL_TextureID texid, bool recompute_size) {
  texture_ = texid;
  if (recompute_size) {
    compute_size();
  }
}

void
GameObject::
set_position (SDL_Point& xy) {
  pixel_position_next_.x = xy.x;
  pixel_position_next_.y = xy.y;
  calculate_next_pixel_rect ();
  update_pixel_position();
}

void
GameObject::
update_pixel_position () {
  pixel_position_ = pixel_position_next_;
  pixel_position_changed_ = false;
  update_pixel_rect();
  blit();
}

bool
GameObject::
check_shape_collision (GameObject* obj, ColliderData* data) const {
  /** $$ This is *temporary* : we only allow a ball as first object.
      but later, lasers will come into the show. */
  if (shape_ != GAME_OBJECT_CIRCLE) {
    return false;
  }
  
  bool collide = false;
  switch (obj->shape_) {
    case GAME_OBJECT_CIRCLE: {
      obj->calculate_next_pixel_position();
      SDL_Point* obj_next_position = obj->get_next_pixel_position();
      collide = Collider::circle_2_circle(
        pixel_position_next_, size_.r,
        *obj_next_position, obj->size_.r,
        data
      );
    }
    break;
    case GAME_OBJECT_RECTANGLE: {
      SDL_Rect obj_next_rect = {
        obj->pixel_position_next_.x,
        obj->pixel_position_next_.y,
        obj->size_.rect.w,
        obj->size_.rect.h
      };
      collide = Collider::circle_2_rectangle(
        pixel_position_next_, size_.r,
        obj_next_rect,
        data
      );
    }
    break;
  }
  return collide;
}

